﻿using iTool.Cloud.Center.ServiceProvider.StorageProvider;
using Orleans;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

namespace iTool.Clustering.Center.ServiceProvider
{
    public class ClusterStorageService : Orleans.Grain, IClusterStorageService
    {
        iStorageStateMaster stateMaster;
        ConcurrentDictionary<string, ConcurrentDictionary<string, string>> iStates;

        public override Task OnActivateAsync()
        {
            var cluster = this.GetPrimaryKeyString();

            this.stateMaster = iStorage.GetClusterStorages(cluster);
            this.iStates = this.stateMaster.States;

            this.stateMaster.StartSubjecter();
            // 初始化数据
            return base.OnActivateAsync();
        }

        public Task ClearStateAsync(string grainType, string key)
        {
            if (this.iStates.TryGetValue(grainType, out ConcurrentDictionary<string, string> state))
            {
                if (state.ContainsKey(key))
                {
                    state.TryRemove(key, out _);
                }
            }
            this.stateMaster.Upsert();
            return Task.CompletedTask;
        }

        public Task<string> ReadStateAsync(string grainType, string key)
        {
            if (this.iStates.TryGetValue(grainType, out ConcurrentDictionary<string, string> state))
            {
                if (state.TryGetValue(key, out string value))
                {
                    return Task.FromResult(value);
                }
            }
            return Task.FromResult(string.Empty);
        }

        public Task WriteStateAsync(string grainType, string key, string value, string etag)
        {
            if (this.iStates.TryGetValue(grainType, out ConcurrentDictionary<string, string> state))
            {
                state.AddOrUpdate(key, value, (k, v) => value);
            }
            else
            {
                state = new ConcurrentDictionary<string, string>();
                state.TryAdd(key, value);
                this.iStates.TryAdd(grainType, state);
            }
            this.stateMaster.Upsert();
            return Task.CompletedTask;
        }
    }
}
